package compilador;



import compilador.pojo.Simbolo;
import java.util.ArrayList;
import java.util.List;



public class TabelaDeSimbolos {


    private List<Simbolo> tabelaDeSimbolo;



    public TabelaDeSimbolos() {
        this.tabelaDeSimbolo = new ArrayList<>();
    }



    /**
     * 
     * @param lexema - Nome do elemento.
     * @param idSimbolo - Identificação do tipo do Simbolo, variável, função, procedimento ou programa.
     * @param tipo - Tipo da Variável / Função - Inteiro ou Booleano
     * @param marcaEscopo 
     * @param posicMemoria - Posição na memória.
     * @param rotuloFuncEProc - Rótulo utilizado pela Função / Procedimento.
     */
    public void insere_tabela(String lexema, String idSimbolo, String tipo, boolean marcaEscopo, String posicMemoria, String rotuloFuncEProc) {


        this.tabelaDeSimbolo.add(new Simbolo(lexema, idSimbolo, tipo, posicMemoria, marcaEscopo, rotuloFuncEProc));
    }



    /**
     * Pesquisa se variável está duplicada dentro do seu contexto.
     *
     * @param lexema
     * @return
     */
    public boolean pesquisa_duplicvar_tabela(String lexema) {


        for (int i = this.tabelaDeSimbolo.size() - 1; i >= 0; i--) {

            Simbolo simbolo = this.tabelaDeSimbolo.get(i);
            if (simbolo.getLexema().equals(lexema)) {
                return true;
            }

            if (simbolo.isMarcaEscopo()) {
                return false;
            }
        }

        return false;

    }



    /**
     * Verifica se o simbolo é uma variável declarada na tabela.
     *
     * @param lexema
     */
    public boolean pesquisa_declvar_tabela(String lexema) {


        for (int i = this.tabelaDeSimbolo.size() - 1; i >= 0; i--) {

            Simbolo simbolo = this.tabelaDeSimbolo.get(i);
            if (simbolo.getLexema().equals(lexema) /*&& simbolo.getIdSimbolo().equals(Simbolo.NOME_VARIAVEL)*/) {

                return true;
            }

            if (simbolo.isMarcaEscopo()) {
             return false;
             }
        }

        return false;

    }

public boolean is_funcao(String lexema) {


        for (int i = this.tabelaDeSimbolo.size() - 1; i >= 0; i--) {

            Simbolo simbolo = this.tabelaDeSimbolo.get(i);
            if (simbolo.getLexema().equals(lexema) && simbolo.getIdSimbolo().equals(Simbolo.NOME_FUNCAO)) {

                return true;
            }
        }

        return false;

    }


public boolean is_corpo_funcao(String lexema) {


        for (int i = this.tabelaDeSimbolo.size() - 1; i >= 0; i--) {

            Simbolo simbolo = this.tabelaDeSimbolo.get(i);
            if( simbolo.isMarcaEscopo()){
                if (simbolo.getLexema().equals(lexema)) {

                    return true;
                }else{
                    return false;
                }
            }
        }

        return false;

    }

    
    public boolean is_variavel(String lexema) {


        for (int i = this.tabelaDeSimbolo.size() - 1; i >= 0; i--) {

            Simbolo simbolo = this.tabelaDeSimbolo.get(i);
            if (simbolo.getLexema().equals(lexema) && simbolo.getIdSimbolo().equals(Simbolo.NOME_VARIAVEL)) {

                return true;
            }
        }

        return false;

    }

    /**
     * Verifica se variável ou função foi declarada na tabela.
     *
     * @param lexema
     * @return
     */
    public boolean pesquisa_declvarfunc_tabela(String lexema) {

        for (int i = this.tabelaDeSimbolo.size() - 1; i >= 0; i--) {

            Simbolo simbolo = this.tabelaDeSimbolo.get(i);
            if (simbolo.getLexema().equals(lexema) && (simbolo.getIdSimbolo().equals(Simbolo.NOME_VARIAVEL) || simbolo.getIdSimbolo().equals(Simbolo.NOME_FUNCAO))) {

                return true;
            }
        }
        return false;
    }



    public boolean pesquisa_declfunc_tabela(String lexema) {

        for (int i = this.tabelaDeSimbolo.size() - 1; i >= 0; i--) {

            Simbolo simbolo = this.tabelaDeSimbolo.get(i);
            if (simbolo.getLexema().equals(lexema) /*&& simbolo.getIdSimbolo().equals(Simbolo.NOME_FUNCAO)*/) {

                return true;
            }
        }
        return false;
    }



    public boolean pesquisa_declproc_tabela(String lexema) {


        for (int i = this.tabelaDeSimbolo.size() - 1; i >= 0; i--) {

            Simbolo simbolo = this.tabelaDeSimbolo.get(i);
            if (simbolo.getLexema().equals(lexema) /*&& simbolo.getIdSimbolo().equals(Simbolo.NOME_PROCEDIMENTO)*/) {

                return true;
            }
        }
        return false;
    }
    
    public boolean is_procedimento(String lexema){
        
        for (int i = this.tabelaDeSimbolo.size() - 1; i >= 0; i--) {

            Simbolo simbolo = this.tabelaDeSimbolo.get(i);
            if (simbolo.getLexema().equals(lexema) && simbolo.getIdSimbolo().equals(Simbolo.NOME_PROCEDIMENTO)) {

                return true;
            }
        }
        return false;
        
    }



    public int pesquisa_tabela(String lexema, String nivel) {

        //TODO com problemas...
        for (int i = this.tabelaDeSimbolo.size() - 1; i >= 0; i--) {

            if (this.tabelaDeSimbolo.get(i).getLexema().equals(lexema)) {
                return i;
            }
        }
        return -1;

    }
    
    public String get_enderecoMemoria( String identificador ){
        
        
        for (int i = this.tabelaDeSimbolo.size() - 1; i >= 0; i--) {
            if (this.tabelaDeSimbolo.get(i).getLexema().equals(identificador)) {
                return this.tabelaDeSimbolo.get(i).getMemoria();
            }
        }
        
        return "";
    }
    
        public String get_rotulo( String identificador ){
        
        
        for (int i = this.tabelaDeSimbolo.size() - 1; i >= 0; i--) {
            if (this.tabelaDeSimbolo.get(i).getLexema().equals(identificador)) {
                return this.tabelaDeSimbolo.get(i).getRotuloFuncEProc();
            }
        }
        
        return "";
    }
    
    
    
    public String pesquisa_tipo_varfunc( String lexema ){
        
        
        for (int i = this.tabelaDeSimbolo.size() - 1; i >= 0; i--) {

            if (this.tabelaDeSimbolo.get(i).getLexema().equals(lexema)) {
                return this.tabelaDeSimbolo.get(i).getTipoVariavelFuncao();
            }
        }
        
        return "";
    }



    public boolean is_funcao(int ind) {

        if (this.tabelaDeSimbolo.get(ind).getIdSimbolo().equals(Simbolo.NOME_FUNCAO)) {

            return true;
        }

        return false;
    }



    public int coloca_tipo_tabela(String tipo) {

        int count = 0;
        for (int i = this.tabelaDeSimbolo.size() - 1; i >= 0; i--) {

            Simbolo simboloTbl = this.tabelaDeSimbolo.get(i);
            if (simboloTbl.getTipoVariavelFuncao().equals("var")) {
                count++;
                this.tabelaDeSimbolo.get(i).setTipoVariavelFuncao(tipo);
            } else {
                break;
            }
        }
        
        return count;
    }



    public int desempilha_tabela() {
        
        int count = 0;

        for (int i = this.tabelaDeSimbolo.size() - 1; i >= 0; i--) {


            if (this.tabelaDeSimbolo.get(i).isMarcaEscopo()) {

                this.tabelaDeSimbolo.get(i).setMarcaEscopo(false);
                break;
            } else {

                if( tabelaDeSimbolo.get(i).getIdSimbolo().equals(Simbolo.NOME_VARIAVEL) || tabelaDeSimbolo.get(i).getIdSimbolo().equals(Simbolo.NOME_FUNCAO) ){
                    count++;
                }
                this.tabelaDeSimbolo.remove(i);
            }
        }
        
        return count;

    }
}
